package ClassLib;

import java.util.*;

//https://leetcode.cn/problems/design-twitter/
public class Twitter {
    private  Integer timeStamp;
    private HashMap<Integer,User> user_map;
    public Twitter() {
        user_map=new HashMap<>();
        timeStamp = 0;
    }

    public void postTweet(int userId, int tweetId) {
        user_map.putIfAbsent(userId,new User(userId));
        User user = user_map.get(userId);
        user.postTweet(tweetId);
    }

    public List<Integer> getNewsFeed(int userId) {
        user_map.putIfAbsent(userId,new User(userId));
        User user = user_map.get(userId);
        return user.getNewsFeed();
    }

    public void follow(int followerId, int followeeId) {
        user_map.putIfAbsent(followerId,new User(followerId));
        user_map.putIfAbsent(followeeId,new User(followeeId));
        user_map.get(followerId).follow(followeeId);
    }

    public void unfollow(int followerId, int followeeId) {
        user_map.putIfAbsent(followerId,new User(followerId));
        user_map.putIfAbsent(followeeId,new User(followeeId));
        user_map.get(followerId).unfollow(followeeId);
    }
     class User{
        private final Integer userId;
        private Tweet next;
        private HashSet<Integer> users;

        public User(Integer userId) {
            this.userId = userId;
            users = new HashSet<>();
            follow(userId);
        }
        public Tweet getNext() {
            return next;
        }
        public List<Integer> getNewsFeed() {
            List<Tweet> list = users.stream().map(x -> user_map.get(x).getNext()).toList();
            return MergeTweetsLimit10(list);
        }
        public void follow(int followeeId) {
            users.add(followeeId);
        }

        public void unfollow(int followeeId) {
            users.remove(followeeId);
        }
        public void postTweet(int tweetId) {
            Tweet tweet = new Tweet(tweetId);
            if(this.next ==null)
                this.next =tweet;
            else {
                tweet.setNext(next);
                next = tweet;
            }
        }
    }

     class Tweet{
        private Integer stamp;
        private Integer id;
        private Tweet next;
        public Tweet(int id) {
            this.id = id;
            stamp=timeStamp++;

        }
        public Tweet getNext() {
            return next;
        }
        public void setNext(Tweet _next) {
            next=_next;
        }
        public Integer getId() {
            return id;
        }
    }
    private List<Integer> MergeTweetsLimit10(List<Tweet> tweets){
        PriorityQueue<Tweet> pq=new PriorityQueue<>((a, b)->b.stamp-a.stamp);
        for (Tweet tweet : tweets) {
            if(tweet!=null){
                pq.offer(tweet);
            }
        }
        List<Integer> ans=new ArrayList<>();
        while (!pq.isEmpty()&&ans.size()<10){
            Tweet poll = pq.poll();
            ans.add(poll.getId());
            if(poll.getNext()!=null){
                pq.offer(poll.getNext());
            }
        }
        return ans;
    }
}
